/**
* File: waypoint.h
*
* \brief Waypoint structures and miscellaneous functions.
*
* \author Instituto Superior Tecnico de Lisboa, Portugal
* \author Technical University of Lisbon, Portugal
* 
* \author Agentes Autonomos e Sistemas Multiagente
* \author Autonomous Agents and Multiagent Systems
* 
* \version	1.0
* \date		2006/2007
**/
#pragma once

#include "../engine.h"
#include "globals.h"
using namespace game;

namespace game{ namespace waypoints{ 
	//=============================================================================
	// Constants and defines
	//=============================================================================
#define WAYPOINT_VERSION    7
#define WAYPOINT_VERSION6   6
#define WAYPOINT_VERSION5   5

#define EXPERIENCE_VERSION  2

#define MAX_WAYPOINTS 1024
#define MAX_STACK_NODES (MAX_WAYPOINTS*4)

#define MAX_PATH_INDEX    8
#define OLDMAX_PATH_INDEX 4

	//=============================================================================
	// Enumerations
	//=============================================================================
	/**
	* \brief Waypoint type flags (32 bits are available)
	**/
	class WaypointFlags{
	public:
		enum Enumeration{
			lift      			=   (1 << 1),  // wait for lift to be down before approaching this waypoint
			crouch    			=   (1 << 2),  // must crouch to reach this waypoint
			crossing  			=   (1 << 3),  // a target waypoint
			goal      			=   (1 << 4),  // mission goal point (bomb,hostage etc.)
			ladder    			=   (1 << 5),  // waypoint is on ladder
			rescue    			=   (1 << 6),  // waypoint is a Hostage Rescue Point
			camp      			=   (1 << 7),  // waypoint is a Camping Point
			noHostage			=   (1 << 8),  // only use this waypoint if no hostage

			terrorist			=   (1 << 29), // It's a specific Terrorist Point
			counterTerrorist	=   (1 << 30), // It's a specific CT Point
		};
	};

	/**
	* \brief Waypoint connection flags (16 bits are available)
	**/
	class WaypointConnectionFlags{
	public:
		enum Enumeration{
			jump      =   (1 << 0),  // Must Jump for this Connection
		};
	};

	//=============================================================================
	// Structures
	//=============================================================================
	/** 
	* \brief Define the waypoint file header structure.
	*/
	typedef struct WaypointHeader_s
	{
		char filetype[8];  // should be "PODWAY!\0"
		int32 waypoint_file_version;
		int32 number_of_waypoints;
		char mapname[MAP_NAME_MAX_SIZE];  // name of map for these waypoints
		char waypointer[32];   // Name of the Waypointer
	} WaypointHeader;

	/**
	* \brief Waypoint structure.
	**/
	typedef struct WaypointStruct {
		int32 pathNumber;
		int32 flags;    // button, lift, flag, health, ammo, etc.
		Vector origin;   // location
		float radius;    // Maximum Distance WPT Origin can be varied
		float campStartX;
		float campStartY;
		float campEndX;
		float campEndY;
		int16 index[MAX_PATH_INDEX];  // indices of waypoints (index -1 means not used)
		uint16 connectflag[MAX_PATH_INDEX];
		Vector vecConnectVel[MAX_PATH_INDEX];
		int32 distance[MAX_PATH_INDEX];
		struct vis_s {
			/** The number of waypoints visible from this waypoint if the agent is standing **/
			uint16 stand;
			/** The number of waypoints visible from this waypoint if the agent is crouching **/
			uint16 crouch;
		} vis;
	} Waypoint;

	/**
	* \brief Waypoint structure used by version 6.
	**/
	typedef struct WaypointStruct6 {
		int32 pathNumber;
		int32 flags;    // button, lift, flag, health, ammo, etc.
		Vector origin;   // location
		float radius;    // Maximum Distance WPT Origin can be varied
		float campStartX;
		float campStartY;
		float campEndX;
		float campEndY;
		int16 index[MAX_PATH_INDEX];  // indices of waypoints (index -1 means not used)
		int32 distance[MAX_PATH_INDEX];
		struct WaypointStruct6 *next;   // link to next structure
	} Waypoint6;

	/**
	* Waypoint structure used by version 5.
	**/
	typedef struct WaypointStruct5 {
		int32 pathNumber;
		int32 flags;    // button, lift, flag, health, ammo, etc.
		Vector origin;   // location
		float radius;    // Maximum Distance WPT Origin can be varied
		float campStartX;
		float campStartY;
		float campEndX;
		float campEndY;
		int16 index[OLDMAX_PATH_INDEX];  // indices of waypoints (index -1 means not used)
		int32 distance[OLDMAX_PATH_INDEX];
		struct WaypointStruct5 *next;   // link to next structure
	} Waypoint5;

	//=============================================================================
	// Global variables
	//=============================================================================
	/** 
	* \brief The array of waypoints.
	**/
	extern Waypoint *g_waypoints[MAX_WAYPOINTS];
	/** 
	* \brief Number of waypoints in the current map.
	**/
	extern int g_numWaypoints;
	/** 
	* \brief Buffer holding terrorist important waypoint indices.
	**/
	extern int *g_terroristWaypoints;
	/** 
	* \brief Number of terrorist important waypoints.
	**/
	extern int g_numTerroristWaypoints;
	/** 
	* \brief Buffer holding counter-terrorist important waypoint indices.
	**/
	extern int *g_counterTerroristWaypoints;
	/** 
	* \brief Number of counter-terrorist important waypoints.
	**/
	extern int g_numCounterTerroristWaypoints;
	/** 
	* \brief Buffer holding goal waypoint indices.
	**/
	extern int *g_goalWaypoints;
	/** 
	* \brief Number of goal waypoints.
	**/
	extern int g_numGoalWaypoints;
	/** 
	* \brief Buffer holding camping waypoint indices.
	**/
	extern int *g_campWaypoints;
	/** 
	* \brief Number of camping waypoints.
	**/
	extern int g_numCampWaypoints;
	/** 
	* \brief Buffer holding rescue waypoint indices.
	**/
	extern int *g_rescueWaypoints;
	/** 
	* \brief Number of rescue waypoints.
	**/
	extern int g_numRescueWaypoints;

	/** 
	* \brief Flag for noclip wpt editing.
	**/
	extern bool g_editNoclip;
	/** 
	* \brief Default folder to load waypoints from.
	**/
	extern cvar_t g_cvarWPTDirname;

	/** 
	* \brief Is waypoint editing on.
	**/
	extern bool g_waypointOn;
	/** 
	* \brief Whether waypoints have changed since being loaded.
	**/
	extern bool g_waypointsChanged;
	/** 
	* \brief Whether auto-waypointing is on.
	**/
	extern bool g_autoWaypointOn;
	/** 
	* \brief Whether to learn a jump waypoint.
	**/
	extern bool g_learnJumpWaypoint;
	extern int g_findWPIndex;
	extern int g_cacheWaypointIndex;
	extern char g_waypointer[32];

	//=============================================================================
	// Function prototypes
	//=============================================================================
	void reset();
	void initializeTypes();
	bool load();
	void save();
	void saveOldFormat();
	bool areValid();

	void calculateVisibility();
	void editingThink();

	void addPath(short int add_index,  short int path_index, float distance);
	void add(int flags);
	void deleteWaypoint();
	void calculateWayzone(int index);
	void changeFlags(int iFlag,char iMode);
	void setRadius(int iRadius);
	void createPath(int iNodeNum);
	void createPath(int iNodeNum1, int iNodeNum2);
	void removePath(int iNodeNum);
	void removePath(int iNodeNum1, int iNodeNum2);

	int findNearest(Vector origin, float min_distance = 9999.0);
	void findAllWithinRadius(Vector vecPos,float fRadius,int *pTab,int *iCount);
	bool areConnected(int a,int b);
	bool isConnected(int iNum);
	bool isReachable(Vector v_src, Vector v_dest, bool bIsInWater = false);
	bool isVisible(int iSourceIndex, int iDestIndex);
	bool isDuckVisible(int iSourceIndex, int iDestIndex);
	bool isStandVisible(int iSourceIndex, int iDestIndex);
	int getPathDistance(int iSourceWaypoint,int iDestWaypoint);
	bool isValidIndex(int index);

	bool isGoalWaypoint(int index);
	bool isCounterTerroristWaypoint(int index);
	bool isTerroristWaypoint(int index);
	bool isCampWaypoint(int index);
	bool isCrouchWaypoint(int index);
}}